將複雜物件的建造過程標準化,確保在建立細節不同的物件時,可以避免步驟的遺漏。
生產飲料(物件)時,步驟是相同的,但是細節不同,假如在生產時遺漏幾個步驟,那最終的產物就不是我們所想要的。於是,可以先建立標準作業程序(SOP),告知全部生產步驟,細節則由實際生產制定。
最後建立一個指揮者,是外界唯一的聯絡窗口,外界不會知道生產的過程,只會知道最終的產品。
作法是:
Abstract Class
。工廠親代:BeverageBuilder
public abstract class BeverageBuilder {
/**
* 宣告開始生產
*/
public abstract void buildStart();
/**
* 取得瓶胚
*/
public abstract void getPreform();
/**
* 加熱瓶胚
*/
public abstract void heatPreform();
/**
* 瓶胚送入吹瓶機模型內吹出成型
*/
public abstract void moldingForm();
/**
* 清洗瓶身
*/
public abstract void cleanForm();
/**
* 吹乾空瓶
*/
public abstract void dryForm();
/**
* 飲料充填
*/
public abstract void fillBeverage();
/**
* 封瓶蓋
*/
public abstract void putOnBottleCap();
/**
* 套上膠膜
*/
public abstract void putOnLabel();
/**
* 收縮膠膜
*/
public abstract void shrinkLabel();
/**
* 宣告完成生產
*/
public abstract void buildFinish();
}
工廠親代:CokeBuilder
、WaterBuilder
、OrangeJuiceBuilder
public class CokeBuilder extends BeverageBuilder {
@Override
public void buildStart() {
System.out.println("工廠即將生產可樂");
}
@Override
public void getPreform() {
System.out.println("取得瓶胚");
System.out.println("送入輸送帶");
}
@Override
public void heatPreform() {
System.out.println("加熱軟化瓶胚");
}
@Override
public void moldingForm() {
System.out.println("送入吹瓶機");
System.out.println("吹出成型");
}
@Override
public void cleanForm() {
System.out.println("送入無菌室");
System.out.println("清洗瓶身內外");
System.out.println("消毒瓶身內外");
}
@Override
public void dryForm() {
System.out.println("吹乾瓶身");
}
@Override
public void fillBeverage() {
System.out.println("飲料裝填:可樂");
}
@Override
public void putOnBottleCap() {
System.out.println("封瓶蓋:紅色瓶蓋");
System.out.println("離開無菌室");
}
@Override
public void putOnLabel() {
System.out.println("套上瓶身膠膜:紅色膠膜");
}
@Override
public void shrinkLabel() {
System.out.println("蒸汽收縮瓶身膠膜");
}
@Override
public void buildFinish() {
System.out.println("可樂生產完成");
}
}
public class WaterBuilder extends BeverageBuilder {
@Override
public void buildStart() {
System.out.println("工廠即將生產礦泉水");
}
@Override
public void getPreform() {
System.out.println("取得瓶胚");
System.out.println("送入輸送帶");
}
@Override
public void heatPreform() {
System.out.println("加熱軟化瓶胚");
}
@Override
public void moldingForm() {
System.out.println("送入吹瓶機");
System.out.println("吹出成型");
}
@Override
public void cleanForm() {
System.out.println("送入無菌室");
System.out.println("清洗瓶身內外");
System.out.println("消毒瓶身內外");
}
@Override
public void dryForm() {
System.out.println("吹乾瓶身");
}
@Override
public void fillBeverage() {
System.out.println("飲料裝填:礦泉水");
}
@Override
public void putOnBottleCap() {
System.out.println("封瓶蓋:白色瓶蓋");
System.out.println("離開無菌室");
}
@Override
public void putOnLabel() {
System.out.println("套上瓶身膠膜:白色膠膜");
}
@Override
public void shrinkLabel() {
System.out.println("蒸汽收縮瓶身膠膜");
}
@Override
public void buildFinish() {
System.out.println("礦泉水生產完成");
}
}
public class OrangeJuiceBuilder extends BeverageBuilder {
@Override
public void buildStart() {
System.out.println("工廠即將生產柳橙汁");
}
@Override
public void getPreform() {
System.out.println("取得瓶胚");
System.out.println("送入輸送帶");
}
@Override
public void heatPreform() {
System.out.println("加熱軟化瓶胚");
}
@Override
public void moldingForm() {
System.out.println("送入吹瓶機");
System.out.println("吹出成型");
}
@Override
public void cleanForm() {
System.out.println("送入無菌室");
System.out.println("清洗瓶身內外");
System.out.println("消毒瓶身內外");
}
@Override
public void dryForm() {
System.out.println("吹乾瓶身");
}
@Override
public void fillBeverage() {
System.out.println("飲料裝填:柳橙汁");
}
@Override
public void putOnBottleCap() {
System.out.println("封瓶蓋:橘色瓶蓋");
System.out.println("離開無菌室");
}
@Override
public void putOnLabel() {
System.out.println("套上瓶身膠膜:橘色膠膜");
}
@Override
public void shrinkLabel() {
System.out.println("蒸汽收縮瓶身膠膜");
}
@Override
public void buildFinish() {
System.out.println("柳橙汁生產完成");
}
}
指揮者:BeverageDirector
public class BeverageDirector {
private BeverageBuilder beverageBuilder;
public void setBeverageBuilder(BeverageBuilder beverageBuilder) {
this.beverageBuilder = beverageBuilder;
}
public void produceBeverage() {
beverageBuilder.buildStart();
beverageBuilder.getPreform();
beverageBuilder.heatPreform();
beverageBuilder.moldingForm();
beverageBuilder.cleanForm();
beverageBuilder.dryForm();
beverageBuilder.fillBeverage();
beverageBuilder.putOnBottleCap();
beverageBuilder.putOnLabel();
beverageBuilder.shrinkLabel();
beverageBuilder.buildFinish();
}
}
進行生產
public class BeverageBuilderSample {
public static void main(String[] args) {
BeverageDirector beverageDirector = new BeverageDirector();
// 生產可樂
System.out.println("---上午的生產目標是可樂---");
CokeBuilder cokeBuilder = new CokeBuilder();
beverageDirector.setBeverageBuilder(cokeBuilder);
beverageDirector.produceBeverage();
System.out.println("---上午目標已完成---\n");
// 生產礦泉水
System.out.println("---下午的生產目標是礦泉水---");
WaterBuilder watBuilder = new WaterBuilder();
beverageDirector.setBeverageBuilder(watBuilder);
beverageDirector.produceBeverage();
System.out.println("---下午目標已完成---\n");
// 生產柳橙汁
System.out.println("---晚上的生產目標是柳橙汁---");
OrangeJuiceBuilder orangeJuiceBuilder = new OrangeJuiceBuilder();
beverageDirector.setBeverageBuilder(orangeJuiceBuilder);
beverageDirector.produceBeverage();
System.out.println("---晚上目標已完成---");
}
}
工廠親代:BeverageBuilder
/** @abstract */
class BeverageBuilder {
/* 宣告開始生產 */
buildStart() { return; }
/* 取得瓶胚 */
getPreform() { return; }
/* 加熱瓶胚 */
heatPreform() { return; }
/* 瓶胚送入吹瓶機模型內吹出成型 */
moldingForm() { return; }
/* 清洗瓶身 */
cleanForm() { return; }
/* 吹乾空瓶 */
dryForm() { return; }
/* 飲料充填 */
fillBeverage() { return; }
/* 封瓶蓋 */
putOnBottleCap() { return; }
/* 套上膠膜 */
putOnLabel() { return; }
/* 收縮膠膜 */
shrinkLabel() { return; }
/* 宣告完成生產 */
buildFinish() { return; }
}
工廠親代:CokeBuilder
、WaterBuilder
、OrangeJuiceBuilder
lass CokeBuilder extends BeverageBuilder {
/** @override */
buildStart() {
console.log("工廠即將生產可樂");
}
/** @override */
getPreform() {
console.log("取得瓶胚");
console.log("送入輸送帶");
}
/** @override */
heatPreform() {
console.log("加熱軟化瓶胚");
}
/** @override */
moldingForm() {
console.log("送入吹瓶機");
console.log("吹出成型");
}
/** @override */
cleanForm() {
console.log("送入無菌室");
console.log("清洗瓶身內外");
console.log("消毒瓶身內外");
}
/** @override */
dryForm() {
console.log("吹乾瓶身");
}
/** @override */
fillBeverage() {
console.log("飲料裝填:可樂");
}
/** @override */
putOnBottleCap() {
console.log("封瓶蓋:紅色瓶蓋");
console.log("離開無菌室");
}
/** @override */
putOnLabel() {
console.log("套上瓶身膠膜:紅色膠膜");
}
/** @override */
shrinkLabel() {
console.log("蒸汽收縮瓶身膠膜");
}
/** @override */
buildFinish() {
console.log("可樂生產完成");
}
}
class WaterBuilder extends BeverageBuilder {
/** @override */
buildStart() {
console.log("工廠即將生產礦泉水");
}
/** @override */
getPreform() {
console.log("取得瓶胚");
console.log("送入輸送帶");
}
/** @override */
heatPreform() {
console.log("加熱軟化瓶胚");
}
/** @override */
moldingForm() {
console.log("送入吹瓶機");
console.log("吹出成型");
}
/** @override */
cleanForm() {
console.log("送入無菌室");
console.log("清洗瓶身內外");
console.log("消毒瓶身內外");
}
/** @override */
dryForm() {
console.log("吹乾瓶身");
}
/** @override */
fillBeverage() {
console.log("飲料裝填:礦泉水");
}
/** @override */
putOnBottleCap() {
console.log("封瓶蓋:白色瓶蓋");
console.log("離開無菌室");
}
/** @override */
putOnLabel() {
console.log("套上瓶身膠膜:白色膠膜");
}
/** @override */
shrinkLabel() {
console.log("蒸汽收縮瓶身膠膜");
}
/** @override */
buildFinish() {
console.log("礦泉水生產完成");
}
}
class OrangeJuiceBuilder extends BeverageBuilder {
/** @override */
buildStart() {
console.log("工廠即將生產柳橙汁");
}
/** @override */
getPreform() {
console.log("取得瓶胚");
console.log("送入輸送帶");
}
/** @override */
heatPreform() {
console.log("加熱軟化瓶胚");
}
/** @override */
moldingForm() {
console.log("送入吹瓶機");
console.log("吹出成型");
}
/** @override */
cleanForm() {
console.log("送入無菌室");
console.log("清洗瓶身內外");
console.log("消毒瓶身內外");
}
/** @override */
dryForm() {
console.log("吹乾瓶身");
}
/** @override */
fillBeverage() {
console.log("飲料裝填:柳橙汁");
}
/** @override */
putOnBottleCap() {
console.log("封瓶蓋:橘色瓶蓋");
console.log("離開無菌室");
}
/** @override */
putOnLabel() {
console.log("套上瓶身膠膜:橘色膠膜");
}
/** @override */
shrinkLabel() {
console.log("蒸汽收縮瓶身膠膜");
}
/** @override */
buildFinish() {
console.log("柳橙汁生產完成");
}
}
指揮者:BeverageDirector
class BeverageDirector {
constructor() {
/** @type BeverageBuilder */
this.beverageBuilder = null;
}
setBeverageBuilder(beverageBuilder) {
this.beverageBuilder = beverageBuilder;
}
produceBeverage() {
this.beverageBuilder.buildStart();
this.beverageBuilder.getPreform();
this.beverageBuilder.heatPreform();
this.beverageBuilder.moldingForm();
this.beverageBuilder.cleanForm();
this.beverageBuilder.dryForm();
this.beverageBuilder.fillBeverage();
this.beverageBuilder.putOnBottleCap();
this.beverageBuilder.putOnLabel();
this.beverageBuilder.shrinkLabel();
this.beverageBuilder.buildFinish();
}
}
進行生產
const BeverageBuilderTest = () => {
const beverageDirector = new BeverageDirector();
// 生產可樂
console.log("---上午的生產目標是可樂---");
const cokeBuilder = new CokeBuilder();
beverageDirector.setBeverageBuilder(cokeBuilder);
beverageDirector.produceBeverage();
console.log("---上午目標已完成---\n");
// 生產礦泉水
console.log("---下午的生產目標是礦泉水---");
const watBuilder = new WaterBuilder();
beverageDirector.setBeverageBuilder(watBuilder);
beverageDirector.produceBeverage();
console.log("---下午目標已完成---\n");
// 生產柳橙汁
console.log("---晚上的生產目標是柳橙汁---");
const orangeJuiceBuilder = new OrangeJuiceBuilder();
beverageDirector.setBeverageBuilder(orangeJuiceBuilder);
beverageDirector.produceBeverage();
console.log("---晚上目標已完成---");
};
BeverageBuilderTest();
Builder 強調「允許細節不同」但物件之間的建立步驟必須相同,才能抽離共同步驟建立標準化流程。
這樣做的好處有幾點:
缺點很明顯,整體程式碼較多,每增加一次新產品(物件),程式碼會大量增加。
明天將介紹 Prototype 模式。